
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using ScrewTurn.Wiki.PluginFramework;
using System.Globalization;

namespace ScrewTurn.Wiki {

	public partial class Edit : BasePage {

		private bool disableAjaxPreview = false;
		private bool previewClassic = false;

        protected void Page_Load(object sender, EventArgs e) {
            Page.Title = Resources.Messages.EditTitle + " - " + Settings.WikiTitle;
			lblPreview.CssClass = "";
            lblPreview.Text = "";

			txtPageName.Attributes.Add("onkeydown", @"javascript:var keycode; if(window.event) keycode = event.keyCode; else keycode = event.which; if(keycode == 9) { __GetServerElementById('txtTitle').focus(); return false; }");
			txtTitle.Attributes.Add("onkeydown", @"javascript:var keycode; if(window.event) keycode = event.keyCode; else keycode = event.which; if(keycode == 9) { __GetServerElementById('txtContent').focus(); return false; }");

			txtContent.Attributes.Add("onkeyup", "javascript:storeCaret(this); return false");
			txtContent.Attributes.Add("onclick", "javascript:storeCaret(this); return false");

			string ua = Request.UserAgent;
			if(!string.IsNullOrEmpty(ua)) {
				ua = ua.ToLowerInvariant();
				StringBuilder sbua = new StringBuilder();
				sbua.Append(@"<script type=""text/javascript"">");
				sbua.Append("\r\n<!--\r\n");
				if(ua.Contains("gecko")) {
					// Mozilla
					sbua.Append("addEventListener('beforeunload', __UnloadPage, true);");
				}
				else {
					// IE
					sbua.Append("window.attachEvent('onbeforeunload', __UnloadPage);");
				}
				sbua.Append("\r\n// -->\r\n");
				sbua.Append("</script>");
				lblUnloadPage.Text = sbua.ToString();

				if(ua.Contains("konqueror") || ua.Contains("safari")) disableAjaxPreview = true;
			}

			PrintRefreshLink();
			PrintStrings();
			PrintEditNotice();
			PrintLabels();
			PrintAjaxEnabler();
			PrintPrePreview();
			PrintPostPreview();
			PrintSessionRefresh();
			PrintCustomSpecialTags();

			if(Request.Cookies[Settings.LoginCookieName] != null && SessionFacade.LoginKey == null) {
				Response.Redirect("/Members/Login.aspx?Redirect=" + Tools.UrlEncode(Request.Url.ToString().Substring(Request.Url.ToString().ToLowerInvariant().IndexOf("edit.aspx"))));
			}

			if(Page.IsPostBack) return;

			// Load PageList
			StringBuilder sb = new StringBuilder();
			List<PageInfo> pages = Pages.Instance.AllPages;
			sb.AppendFormat("<script type=\"text/javascript\">\r\n<!--\r\n__AllPages = new Array({0});\r\n", pages.Count);
			for(int i = 0; i < pages.Count; i++) {
				sb.AppendFormat("__AllPages[{0}] = '{1}'; ", i, pages[i].Name.Replace("'", "&apos;"));
			}
			sb.Append("// -->\r\n</script>\r\n");
			lblPageList.Text = sb.ToString();

			// Load snippets
			StringBuilder sb2 = new StringBuilder();
			List<Snippet> snippets = Snippets.Instance.AllSnippets;
			for(int i = 0; i < snippets.Count; i++) {
				sb2.Append(@"<a href=""#"" class=""snippetlistlink"" onclick=""javascript:return __Insert('{S:");
				sb2.Append(snippets[i].Name.Replace("'", "&apos;"));
				int parms = CountParameters(snippets[i]);
				for(int k = 0; k < parms; k++) {
					sb2.AppendFormat("|P{0}", k + 1);
				}
				sb2.Append(@"}');"">");
				sb2.Append(snippets[i].Name);
				if(parms > 0) {
					sb2.AppendFormat(" ({0} parms)", parms);
				}
				sb2.Append("</a>");
			}
			lblSnippetList.Text = sb2.ToString();

            if(Request["File"] != null) {
				if(SessionFacade.LoginKey == null || !SessionFacade.Admin) {
					Response.Redirect("AccessDenied.aspx");
				}

				// Check filename to avoid editing of unallowed files
				string filename = Request["File"].ToLower(CultureInfo.CurrentCulture);
				string[] editableFiles = Settings.EditableFiles;
				bool found = false;
				for(int i = 0; i < editableFiles.Length; i++) {
					if(filename.Equals(editableFiles[i].ToLower(CultureInfo.CurrentCulture))) {
						found = true;
						break;
					}
				}
				if(!found) {
					Response.Redirect("AccessDenied.aspx");
				}

                txtPageName.Visible = false;
                txtTitle.Visible = false;
                lblTitle.Visible = false;
				lblCategories.Visible = false;
				lstCategories.Visible = false;
				lblNewCategoryResult.Visible = false;
				txtNewCategory.Visible = false;
				btnNewCategory.Visible = false;
				lblEditComment.Visible = false;
				txtComment.Visible = false;
                lblGlobalTitle.Text = Resources.Messages.EditingFile + ": " + Request["File"];
                if(!File.Exists(Settings.PublicDirectory + Request["File"])) {
					lblPreview.CssClass = "resulterror";
					lblPreview.Text = Resources.Messages.FileNotFound;
                    return;
                }
                txtContent.Text = Tools.LoadFile(Settings.PublicDirectory + Request["File"]);
                if(Request["Action"] != null && Request["Action"].ToLowerInvariant().Equals("edit")) {
                }
                else {
                    txtContent.ReadOnly = true;
                    btnSave.Enabled = false;
                }
                return;
            }

			PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);

			if(Request["Page"] != null && Pages.IsValidName(Request["Page"])) {
				txtUploadDirectory.Text = Request["Page"];
			}

            if(pageInfo == null) {
				if(SessionFacade.LoginKey == null) {
					if(!Settings.PublicAccess) {
						Response.Redirect("/Members/Login.aspx?Redirect=Edit.aspx");
					}
				}
				else {
					if(!Settings.UsersCanCreateNewPages && !SessionFacade.Admin) {
						Response.Redirect("AccessDenied.aspx");
					}
				}
                lblGlobalTitle.Text = Resources.Messages.CreatePage + ": ";
                txtPageName.Visible = true;
            }

			// Display only legal Categories (i.e. Categories managed by the provider of the page, or the default provider is the page is not available)
			List<CategoryInfo> cats = new List<CategoryInfo>(Pages.Instance.GetAvailableCategories(pageInfo));
			cats.Sort(new CategoryNameComparer());
			lstCategories.Items.Clear();
			for(int i = 0; i < cats.Count; i++) {
				lstCategories.Items.Add(new ListItem(cats[i].Name + "&nbsp;&nbsp;&nbsp;&nbsp;", cats[i].Name));
			}

			if((!Settings.UsersCanManagePageCategories && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
				(!Settings.UsersCanManagePageCategories && SessionFacade.LoginKey == null)) {
				// Disable Category management
				lstCategories.Enabled = false;
			}
			if((!Settings.UsersCanCreateNewCategories && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
				(!Settings.UsersCanCreateNewCategories && SessionFacade.LoginKey == null)) {
				// Disable Category creation
				txtNewCategory.Visible = false;
				btnNewCategory.Visible = false;
				lblNewCategoryResult.Visible = false;
			}
			if((!Settings.UsersCanUploadFiles && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
				(!Settings.UsersCanUploadFiles && SessionFacade.LoginKey == null)) {
				// Disable Quick Upload
				updFile.Enabled = false;
			}

            if(pageInfo != null) {
				if(pageInfo.Provider.ReadOnly) Response.Redirect(pageInfo.Name + Settings.PageExtension);

                if(pageInfo.Status == PageStatus.Locked) {
					if(SessionFacade.LoginKey == null || (SessionFacade.LoginKey != null && (SessionFacade.LoginKey == null || !SessionFacade.Admin))) {
                        Response.Redirect("AccessDenied.aspx");
                    }
                }

                // Login/Authorization check
				if(SessionFacade.LoginKey == null && !Settings.PublicAccess && pageInfo.Status != PageStatus.Public) {
					Response.Redirect("/Members/Login.aspx?Redirect=" + Tools.UrlEncode(Request.Url.ToString().Substring(Request.Url.ToString().ToLowerInvariant().IndexOf("edit.aspx"))));
                }
				if((Settings.PublicAccess || pageInfo.Status == PageStatus.Public) && SessionFacade.LoginKey == null) {
                    lblIpLogged.Visible = true;
                }

				CheckEditingCollisions();

                lblGlobalTitle.Text = Resources.Messages.EditPage + ": " + pageInfo.Name;
                PageContent c = Content.GetPageContent(pageInfo, false);

                txtTitle.Text = c.Title;

				if(Request["Section"] != null) {
					// Load only a single section of the page
					int section = -1;
					try {
						section = int.Parse(Request["Section"]);
					}
					catch {
					}
					if(section == -1) txtContent.Text = c.Content;
					else {
						List<HPosition> hPos = Formatter.DetectHeaders(c.Content);
						int start, len;
						string dummy = "";
						ExtractSection(c.Content, section, out start, out len, out dummy);
						txtContent.Text = c.Content.Substring(start, len);
						// Extract the title of the selected Section
						string sectionTitle = txtContent.Text.Split('\n')[0];
						sectionTitle = sectionTitle.Substring(0, sectionTitle.LastIndexOf("==")); // Search for at at least two '='
						sectionTitle = sectionTitle.Trim('=');
						// Append it to the Global Title
						lblGlobalTitle.Text += " / " + sectionTitle/* + " [" + section.ToString() + "]"*/;
					}
					// This is needed to avoid content corruption
					btnSaveAndContinue.Visible = false;
				}
				else {
					txtContent.Text = c.Content;
				}

				// Select currently used Categories
				CategoryInfo[] categories = Pages.Instance.GetCategoriesPerPage(pageInfo);
				for(int i = 0; i < categories.Length; i++) {
					for(int k = 0; k < lstCategories.Items.Count; k++) {
						if(categories[i].Name.Equals(lstCategories.Items[k].Value)) {
							lstCategories.Items[k].Selected = true;
							break;
						}
					}
				}
            }
            else {
				if(SessionFacade.LoginKey == null && !Settings.PublicAccess) {
					Response.Redirect("/Members/Login.aspx?Redirect=Edit.aspx?Page=" + Request["Page"]);
				}
				if(!Settings.UsersCanCreateNewPages && !SessionFacade.Admin) {
                    Response.Redirect("AccessDenied.aspx");
                }
                lblGlobalTitle.Text = Resources.Messages.CreatePage + ": ";
                txtPageName.Visible = true;
                txtPageName.Text = Request["Page"];

				if(SessionFacade.Admin) {
					pnlProvider.Visible = true;

					IPagesStorageProvider[] pgs = Collectors.PagesProviderCollector.AllProviders;
					for(int i = 0; i < pgs.Length; i++) {
						if(!pgs[i].ReadOnly) {
							ListItem li = new ListItem(pgs[i].Information.Name, pgs[i].GetType().ToString());
							if(pgs[i].GetType().ToString().Equals(Settings.DefaultPagesProvider)) li.Selected = true;
							lstProvider.Items.Add(li);
						}
					}
				}
            }

			captcha.Visible = SessionFacade.LoginKey == null && !Settings.DisableCaptchaControl;

        }

		private int CountParameters(Snippet s) {
			Regex regex = new Regex("\\?[0-9]+\\?");
			List<string> parms = new List<string>();
			foreach(Match m in regex.Matches(s.Content)) {
				if(m.Success && !parms.Contains(m.Value)) parms.Add(m.Value);
			}
			return parms.Count;
		}

		private void ExtractSection(string content, int section, out int start, out int len, out string anchor) {
			List<HPosition> hPos = Formatter.DetectHeaders(content);
			start = 0;
			len = content.Length;
			anchor = "";
			int level = -1;
			bool found = false;
			for(int i = 0; i < hPos.Count; i++) {
				if(hPos[i].ID == section) {
					start = hPos[i].Index;
					len = len - start;
					level = hPos[i].Level; // Level is used to edit the current section AND all the subsections
					// Set the anchor value so that it's possible to redirect the user to the just edited section
					anchor = Formatter.BuildHAnchor(hPos[i].Text);
					found = true;
					break;
				}
			}
			if(found) {
				int diff = len;
				for(int i = 0; i < hPos.Count; i++) {
					if(hPos[i].Index > start && // Next section (Hx)
						hPos[i].Index - start < diff && // The nearest section
						hPos[i].Level <= level) { // Of the same level or higher
						len = hPos[i].Index - start - 1;
						diff = hPos[i].Index - start;
					}
				}
			}
		}

		private void PrintCustomSpecialTags() {
			Dictionary<string, CustomToolbarItem> tags = Host.Instance.CustomSpecialTags;
			StringBuilder sb = new StringBuilder(100);
			foreach(string key in tags.Keys) {
				switch(tags[key].Item) {
					case ToolbarItem.SpecialTag:
						sb.AppendFormat("<a href=\"#\" onclick=\"javascript:return __Insert('{0}');\" class=\"specialtaglink\">{1}</a>",
							tags[key].Value, key);
						break;
					case ToolbarItem.SpecialTagWrap:
						string[] t = tags[key].Value.Split('|');
						sb.AppendFormat("<a href=\"#\" onclick=\"javascript:return __Wrap('{0}', '{1}');\" class=\"specialtaglink\">{2}</a>",
							t[0], t[1], key);
						break;
				}
			}
			lblCustomSpecialTags.Text = sb.ToString();
		}

		private void PrintLabels() {
			if(Page.IsPostBack) return;

			lblFileManagement.Text = Resources.Messages.FileManagement;

			lblBuildAnchor.Text = Resources.Messages.Anchor;
			lblBuildAnchorLink.Text = Resources.Messages.AnchorLink;

			lblImageLeft.Text = Resources.Messages.ImageLeft;
			lblImageRight.Text = Resources.Messages.ImageRight;
			lblImageAuto.Text = Resources.Messages.ImageAuto;
			lblImageInline.Text = Resources.Messages.ImageInline;

			lblTextareaSize.Text = Resources.Messages.TextareaSize;
			lblBigger.Text = Resources.Messages.Bigger;
			lblSmaller.Text = Resources.Messages.Smaller;
			lblAuto.Text = Resources.Messages.Auto;
		}

		private void CheckEditingCollisions() {
			PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);
			if(pageInfo == null) return;

			string username = Request.UserHostAddress;
			if(SessionFacade.LoginKey != null) username = SessionFacade.Username;

			if(Collisions.Instance.IsEdited(pageInfo, username)) {
				pnlConcurrentEditing.Visible = true;
				lblConcurrentEditingUsername.Text = "(" + Users.Instance.UserLink(Collisions.Instance.WhosEditing(pageInfo)) + ")";
				if(Settings.DisableConcurrentEditing) {
					lblSaveDisabled.Visible = true;
					lblSaveDangerous.Visible = false;
					btnSave.Enabled = false;
					btnSaveAndContinue.Enabled = false;
				}
				else {
					lblSaveDisabled.Visible = false;
					lblSaveDangerous.Visible = true;
					btnSave.Enabled = true;
					btnSaveAndContinue.Enabled = true;
				}
			}
			else {
				pnlConcurrentEditing.Visible = false;
				btnSave.Enabled = true;
				btnSaveAndContinue.Enabled = true;
			}
		}

		public void PrintEditNotice() {
			string n;
			if(!Content.PseudoCache.TryGetValue("EditNotice", out n)) {
				n = Formatter.Format(Tools.LoadFile(Settings.EditNoticeFile), null);
				Content.PseudoCache["EditNotice"] = n;
			}
			lblEditNotice.Text = "<br /><br />" + n;
		}

		protected void btnSaveAndContinue_Click(object sender, EventArgs e) {
			btnSave_Click(sender, e);
		}

        protected void btnSave_Click(object sender, EventArgs e) {
			if(!Page.IsValid) return;

			// Re-verify authentication
			PageInfo pageInfo = Pages.Instance.FindPage(Request["Page"]);
			if(pageInfo == null) {
				// Page creation
				if(SessionFacade.LoginKey == null && !Settings.PublicAccess) {
					Response.Redirect("/Members/Login.aspx?Redirect=Edit.aspx?Page=" + Request["Page"]);
				}
				if(!Settings.UsersCanCreateNewPages && !SessionFacade.Admin) {
					Response.Redirect("AccessDenied.aspx");
				}
			}
			else {
				// Page modification
				if(pageInfo.Provider.ReadOnly) Response.Redirect(pageInfo.Name + Settings.PageExtension);

				if(pageInfo.Status == PageStatus.Locked) {
					if(SessionFacade.LoginKey == null || (SessionFacade.LoginKey != null && (SessionFacade.LoginKey == null || !SessionFacade.Admin))) {
						Response.Redirect("AccessDenied.aspx");
					}
				}

				// Login/Authorization check
				if(SessionFacade.LoginKey == null && !Settings.PublicAccess && pageInfo.Status != PageStatus.Public) {
					Response.Redirect("/Members/Login.aspx?Redirect=" + Tools.UrlEncode(Request.Url.ToString().Substring(Request.Url.ToString().ToLowerInvariant().IndexOf("edit.aspx"))));
				}
				if((Settings.PublicAccess || pageInfo.Status == PageStatus.Public) && SessionFacade.LoginKey == null) {
					lblIpLogged.Visible = true;
				}
			}

            // Check for scripts
            if(!Settings.ScriptTagsAllowed) {
                Regex r = new Regex(@"\<script.*?\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                if(r.Match(txtContent.Text).Success) {
					lblResult.Text = @"<span style=""color: #FF0000;"">" + Resources.Messages.ScriptDetected + "</span>";
                    return;
                }
            }

			bool redirect = true;
			if(sender == btnSaveAndContinue) redirect = false;

            if(Request["File"] != null) {
				Log.LogEntry("File update requested for " + Request["File"], EntryType.General, SessionFacade.Username);
                Tools.WriteFile(Settings.PublicDirectory + Request["File"], txtContent.Text);
				Content.PseudoCache.Clear();
                if(redirect) Response.Redirect("Admin.aspx");
				lblResult.Text = Resources.Messages.FileSaved;
                return;
            }

			txtPageName.Style.Clear();
			txtTitle.Style.Clear();

            lblResult.Text = "";
			lblResult.CssClass = "";

            if(txtPageName.Visible && txtPageName.Enabled) {
                if(!Pages.IsValidName(txtPageName.Text)) {
					lblResult.CssClass = "resulterror";
					lblResult.Text = Resources.Messages.InvalidPageName;
					txtPageName.Style.Add("background-color", "#FF6600");
                    return;
                }
                else {
                    PageInfo info = Pages.Instance.FindPage(txtPageName.Text);
                    if(info != null) {
						lblResult.CssClass = "resulterror";
						lblResult.Text = Resources.Messages.PageAlreadyExists;
						txtPageName.Style.Add("background-color", "#FF6600");
                        return;
                    }
                }
            }
            if(txtTitle.Text.Replace(" ", "").Length == 0) {
				lblResult.CssClass = "resulterror";
				lblResult.Text = Resources.Messages.InvalidPageTitle;
				txtTitle.Style.Add("background-color", "#FF6600");
                return;
            }

            string username = "";
			if(SessionFacade.LoginKey == null) username = Request.UserHostAddress;
			else username = SessionFacade.Username;

			// Create list of selected categories
			List<CategoryInfo> categories = new List<CategoryInfo>();
			for(int i = 0; i < lstCategories.Items.Count; i++) {
				if(lstCategories.Items[i].Selected) categories.Add(Pages.Instance.FindCategory(lstCategories.Items[i].Value));
			}

			txtComment.Text = txtComment.Text.Trim();

            if(txtPageName.Visible) {
				PageInfo pg = Pages.Instance.FindPage(txtPageName.Text);
				bool bak = true;
				if(pg == null) {
					if(pnlProvider.Visible) Pages.Instance.CreatePage(txtPageName.Text, Collectors.PagesProviderCollector.GetProvider(lstProvider.SelectedValue));
					else Pages.Instance.CreatePage(txtPageName.Text);
					pg = Pages.Instance.FindPage(txtPageName.Text);
					bak = false;
					txtUploadDirectory.Text = pg.Name;
				}
                Log.LogEntry("Page update requested for " + txtPageName.Text, EntryType.General, username);
				Pages.Instance.ModifyPage(pg, txtTitle.Text, username, DateTime.Now, txtComment.Text, txtContent.Text, bak);
				Pages.Instance.Rebind(pg, categories.ToArray());
				lblResult.Text = "<span style=\"color: #009900;\">" + Resources.Messages.PageSaved + "</span>";

				if(redirect) {
					Collisions.Instance.Cancel(pg, username);
					Response.Redirect(Tools.UrlEncode(txtPageName.Text) + Settings.PageExtension + "?NoRedirect=1");
				}
				else {
					// Disable PageName, because the name cannot be changed anymore
					txtPageName.Enabled = false;
				}
            }
            else {
				// Used for redirecting to a specific section after editing it
				string anchor = "";

				PageInfo info = Pages.Instance.FindPage(Request["Page"]);
				if(Request["Section"] == null && txtContent.Text.Replace("\r", "").Equals(Content.GetPageContent(info, false).Content)) {
					// Save only MetaData
					Log.LogEntry("Page Meta update requested for " + info.Name, EntryType.General, username);
					Pages.Instance.ModifyPage(info, txtTitle.Text, username, DateTime.Now, txtComment.Text, txtContent.Text, false);
				}
				else {
					// Save all the data
					Log.LogEntry("Page update requested for " + info.Name, EntryType.General, username);
					int section = -1;
					try {
						section = int.Parse(Request["Section"]);
					}
					catch {
					}
					if(section == -1) {
						Pages.Instance.ModifyPage(info, txtTitle.Text, username, DateTime.Now, txtComment.Text, txtContent.Text, true);
					}
					else {
						StringBuilder sb = new StringBuilder();
						PageContent cont = Content.GetPageContent(info, false);
						int start, len;
						ExtractSection(cont.Content, section, out start, out len, out anchor);
						if(start > 0) sb.Append(cont.Content.Substring(0, start));
						sb.Append(txtContent.Text);
						if(start + len < cont.Content.Length - 1) sb.Append(cont.Content.Substring(start + len));
						Pages.Instance.ModifyPage(info, txtTitle.Text, username, DateTime.Now, txtComment.Text, sb.ToString(), true);
					}
				}
				// Save Categories binding
				Pages.Instance.Rebind(info, categories.ToArray());

				lblResult.Text = "<span style=\"color: #009900;\">" + Resources.Messages.PageSaved + "</span>";
				if(redirect) {
					Collisions.Instance.Cancel(info, username);
					Response.Redirect(Tools.UrlEncode(info.Name) + Settings.PageExtension + "?NoRedirect=1" +
						(!string.IsNullOrEmpty(anchor) ? ("#" + anchor) : ""));
				}
            }

        }

		protected void btnPreview_Click(object sender, EventArgs e) {
			// Check for scripts
			if(!Settings.ScriptTagsAllowed) {
				Regex r = new Regex(@"\<script.*?\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
				if(r.Match(txtContent.Text).Success) {
					lblResult.CssClass = "resulterror";
					lblResult.Text = Resources.Messages.ScriptDetected;
					return;
				}
			}

			previewClassic = true;

			lblPrePreview.Text = "";

			lblPreview.Text = "";
			lblPreview.Text = @"<div id=""PreviewDivExternal"">";
			lblPreview.Text += @"<p><a href=""javascript:__HidePreview();"">" + Resources.Messages.HidePreview + @"</a><br />";
			lblPreview.Text += @"<span style=""color: #FF0000;"">" + Resources.Messages.ThisIsAPreview + "</span></p><br />";
			lblPreview.Text += @"<div id=""PreviewDiv"">";

			lblPreview.Text += Formatter.Format(txtContent.Text, null);

			lblPreview.Text += "</div>";
			lblPreview.Text += @"</div><div class=""clear"" />";

			lblPostPreview.Text = "";

			lblResult.Text = @"<span style=""color: #009900;"">" + Resources.Messages.PreviewCreated + "</span>";
		}

		public void PrintAjaxEnabler() {
			if(!disableAjaxPreview) {
				StringBuilder sb = new StringBuilder();
				sb.Append(@"<script type=""text/javascript"">" + "\n<!--\n");
				sb.Append("__GetServerElementById('btnPreview').onclick = __LoadPreview;" + "\n");
				sb.Append("// -->\n</script>" + "\n");
				lblAjaxEnabler.Text = sb.ToString();
			}
			else lblAjaxEnabler.Text = "";
		}

		public void PrintPrePreview() {
			if(!disableAjaxPreview && !previewClassic) {
				StringBuilder sb = new StringBuilder();
				sb.Append(@"<div id=""PreviewDivExternal"" style=""display: none;"">");
				sb.Append(@"<p><a href=""#"" onclick=""__HidePreview();"">");
				sb.Append(Resources.Messages.HidePreview);
				sb.Append("</a><br />");
				sb.Append(@"<span style=""color: #FF0000;"">");
				sb.Append(Resources.Messages.ThisIsAPreview);
				sb.Append("</span></p><br />");
				sb.Append(@"<div id=""PreviewDiv"">");
				lblPrePreview.Text = sb.ToString();
			}
			else lblPrePreview.Text = "";
		}

		public void PrintPostPreview() {
			if(!disableAjaxPreview && !previewClassic) {
				lblPostPreview.Text = @"</div></div><div class=""clear"" />";
			}
			else lblPostPreview.Text = "";
		}

        protected void btnCancel_Click(object sender, EventArgs e) {
            if(txtPageName.Visible) {
				Response.Redirect(Settings.DefaultPage + Settings.PageExtension);
            }
            else {
				PageInfo p = Pages.Instance.FindPage(Request["Page"]);
				string username = Request.UserHostAddress;
				if(SessionFacade.LoginKey != null) username = SessionFacade.Username;

				if(p != null) {
					Collisions.Instance.Cancel(p, username);
					Response.Redirect(Request["Page"] + Settings.PageExtension);
				}
				else if(Request["File"] != null) Response.Redirect("Admin.aspx");
            }
        }

		public void PrintStrings() {
			StringBuilder sb = new StringBuilder();
			sb.Append(@"<script type=""text/javascript"">" + "\n<!--\n");
			sb.Append(@"var __StringLinkTitle = """ + Resources.Messages.LinkTitle + @""";" + "\n");
			sb.Append(@"var __StringLinkUrl = """ + Resources.Messages.LinkUrl + @""";" + "\n");
			sb.Append(@"var __StringAnchorId = """ + Resources.Messages.AnchorId + @""";" + "\n");
			sb.Append(@"var __StringAnchorTitle = """ + Resources.Messages.AnchorTitle + @""";" + "\n");
			sb.Append(@"var __StringImageTitle = """ + Resources.Messages.ImageTitle + @""";" + "\n");
			sb.Append(@"var __StringImageUrl = """ + Resources.Messages.ImageUrl + @""";" + "\n");
			sb.Append(@"var __StringImageBigUrl = """ + Resources.Messages.ImageBigUrl + @""";" + "\n");
			sb.Append(@"var __PreviewCreated = """ + Resources.Messages.PreviewCreated + @""";" + "\n");
			sb.Append(@"var __EnterTitleAndUrl = """ + Resources.Messages.EnterTitleAndUrl + @""";" + "\n");
			sb.Append(@"var __ScriptDetected = """ + Resources.Messages.ScriptDetected + @""";" + "\n");
			sb.Append(@"var __ScriptAllowed = " + Settings.ScriptTagsAllowed.ToString().ToLowerInvariant() + @";" + "\n");
			sb.Append("// -->\n</script>" + "\n");
			lblStrings.Text = sb.ToString();
		}

		protected void btnNewCategory_Click(object sender, EventArgs e) {
			lblNewCategoryResult.Text = "";
			lblNewCategoryResult.CssClass = "";

			if(!Pages.IsValidName(txtNewCategory.Text)) {
				lblNewCategoryResult.CssClass = "resulterror";
				lblNewCategoryResult.Text = Resources.Messages.InvalidCategoryName;
				return;
			}
			if(Pages.Instance.FindCategory(txtNewCategory.Text) == null) {
				PageInfo p = null;
				p = Pages.Instance.FindPage(Request["Page"]);

				if(pnlProvider.Visible) {
					Pages.Instance.CreateCategory(txtNewCategory.Text, Collectors.PagesProviderCollector.GetProvider(lstProvider.SelectedValue));
				}
				else {
					Pages.Instance.CreateCategory(txtNewCategory.Text, (p != null ? p.Provider : null));
				}

				// Save selected categories
				List<string> selected = new List<string>();
				for(int i = 0; i < lstCategories.Items.Count; i++) {
					if(lstCategories.Items[i].Selected) selected.Add(lstCategories.Items[i].Value);
				}

				// Reload list
				lstCategories.Items.Clear();
				CategoryInfo[] cats = null;
				if(pnlProvider.Visible) {
					cats = Collectors.PagesProviderCollector.GetProvider(lstProvider.SelectedValue).AllCategories;
				}
				else {
					cats = Pages.Instance.GetAvailableCategories(p);
				}
				for(int i = 0; i < cats.Length; i++) {
					lstCategories.Items.Add(new ListItem(cats[i].Name + "&nbsp;&nbsp;&nbsp;&nbsp;", cats[i].Name));
				}

				// Re-select correct categories and the new one
				for(int i = 0; i < lstCategories.Items.Count; i++) {
					bool found = false;
					for(int k = 0; k < selected.Count; k++) {
						if(lstCategories.Items[i].Value.Equals(selected[k])) {
							found = true;
							break;
						}
					}
					if(found || lstCategories.Items[i].Value.Equals(txtNewCategory.Text)) lstCategories.Items[i].Selected = true;
				}
			}
			txtNewCategory.Text = "";
		}

		protected void lstProvider_SelectedIndexChanged(object sender, EventArgs e) {
			CategoryInfo[] cats = Collectors.PagesProviderCollector.GetProvider(lstProvider.SelectedValue).AllCategories;
			lstCategories.Items.Clear();
			for(int i = 0; i < cats.Length; i++) {
				lstCategories.Items.Add(new ListItem(cats[i].Name + "&nbsp;&nbsp;&nbsp;&nbsp;", cats[i].Name));
			}
		}

		public void PrintRefreshLink() {
			PageInfo page = Pages.Instance.FindPage(Request["Page"]);
			if(page != null) {
				lblRefreshLink.Text = @"<a href=""Edit.aspx?Page=" + Tools.UrlEncode(page.Name) + (Request["Section"] != null ? "&amp;Section=" + Request["Section"] : "") + @""">" + Resources.Messages.Refresh + " &raquo;</a>";
			}
		}

		public void PrintSessionRefresh() {
			PageInfo p = Pages.Instance.FindPage(Request["Page"]);
			StringBuilder sb = new StringBuilder();
			sb.Append(@"<iframe src=""");
			if(p != null) sb.Append("SessionRefresh.aspx?Page=" + Tools.UrlEncode(p.Name));
			else sb.Append("SessionRefresh.aspx");
			sb.Append(@""" style=""width: 1px; height: 1px; border: none;"" scrolling=""no""></iframe>");

			lblSessionRefresh.Text = sb.ToString();
		}

		protected void btnUpload_Click(object sender, EventArgs e) {
			lblUploadResult.Text = "";

			if((!Settings.UsersCanUploadFiles && (SessionFacade.LoginKey != null && !SessionFacade.Admin)) ||
				(!Settings.UsersCanUploadFiles && SessionFacade.LoginKey == null)) {
				// Upload not allowed
				Response.Redirect("AccessDenied.aspx");
			}

			string partialName = txtUploadDirectory.Text + "\\" + updFile.FileName;
			string fullName = Settings.UploadDirectory + partialName;
			fullName = fullName.Replace("\\\\", "\\");

			if(!updFile.HasFile) {
				lblUploadResult.CssClass = "resulterror";
				lblUploadResult.Text = Resources.Messages.FileVoid;
				return;
			}
			if(File.Exists(fullName)) {
				lblUploadResult.CssClass = "resulterror";
				lblUploadResult.Text = Resources.Messages.FileAlreadyExists;
				return;
			}
			string[] allowedFileTypes = Settings.AllowedFileTypes;
			bool found = false;
			for(int i = 0; i < allowedFileTypes.Length; i++) {
				if(Path.GetExtension(updFile.FileName).ToLower(CultureInfo.CurrentCulture).Equals("." + allowedFileTypes[i].ToLowerInvariant())) {
					found = true;
					break;
				}
			}
			if(!found) {
				Log.LogEntry("Unallowed file type upload attempt blocked (" + Path.GetExtension(updFile.FileName) + ")", EntryType.Warning, SessionFacade.Username);
				lblUploadResult.CssClass = "resulterror";
				lblUploadResult.Text = Resources.Messages.UnallowedFileType;
				return;
			}
			if(updFile.FileBytes.Length > Settings.MaxFileSize * 1024) {
				Log.LogEntry("File too big (" + updFile.FileBytes.Length.ToString() + ")", EntryType.Warning, SessionFacade.Username);
				lblUploadResult.CssClass = "resulterror";
				lblUploadResult.Text = Resources.Messages.FileTooBig;
				return;
			}
			// Delete cached thumbnails (if any)
			Tools.DeleteThumbnails(partialName);
			if(!Directory.Exists(Path.GetDirectoryName(fullName))) Directory.CreateDirectory(Path.GetDirectoryName(fullName));
			updFile.SaveAs(fullName);
			lblUploadResult.CssClass = "resultok";
			lblUploadResult.Text = Resources.Messages.FileSaved;
			Log.LogEntry("File " + updFile.FileName + " uploaded", EntryType.General, SessionFacade.Username);

			jsftTree.RenderContent();
			jsimBrowser.RenderContent();
		}

	}

}
